/**
 *          Hi3861： gpio ADC功能
 *  读取 GPIO5 不同按键电压（主板有user按键，oled拓展板有S1、S2）
 *  控制led，GPIO9-0 灯亮
 * 查阅润和Hi3861硬件资料可知:
 *        1)一共8个ADC通道，ADC0--ADC7  但通道7为参考电压，不能adc转换。
        * 2)GPIO5---ADC2 第3通道
        * 3)各个按键ADC值上下限如下：
        * GPIO5 ---user按键 [5,228]
        *       ---S1 按键  [228,455]
        *       ---S2 按键  [455,682]
        *       ---无按键按下[1422,1820] 也就是GPIO是上拉输入
 * 思路： ①轮询按键方式读取（调用内核接口创建线程任务）
 *        ②中断方式读取
 * 这里只演示第①种方式。
 * Code By: HelloKun 2021.09.01
 * */

#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"  //==系统依赖 包括usleep()

#include "iot_gpio.h"  //==IoTGpioInit()、IoTGpioSetDir()、IoTGpioSetOutPutVal();
#include "hi_io.h"     //==hi_io_set_func()、hi_io_set_pull()
#include "hi_adc.h"    //==hi_adc_read()

#define KEY_TASK_STACK_SIZE 512
#define KEY_TASK_PRIO 24
#define KEY_TEST_GPIO 5 //连接GPIO5 
#define LED_GPIO_9 9    //LED一端通过电阻R6上拉接到V3.3

typedef enum {         //==枚举电压范围
    ADC_USR_MIN = 5,
    ADC_USR_MAX = 228,
    ADC_S1_MIN,  //==229
    ADC_S1_MAX  = 512,
    ADC_S2_MIN,  //==513
    ADC_S2_MAX  = 854
}AdcValue;

typedef enum {  //==对应的按键标识
    SSU_NONE,   //==0
    SSU_USER,
    SSU_S1,
    SSU_S2      //==3
}KeyCode;

//读取电压值
unsigned short int button_adc_get(void)
{
    unsigned short int data;
    if (hi_adc_read( HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_1, HI_ADC_CUR_BAIS_DEFAULT, 0) == 0) {  
        printf("ADC2 %d \n",data);
        return data;    
    }
}

//判断具体是哪个按键按下
unsigned short int button_pressed_check(unsigned short int data)
{
    KeyCode ret = SSU_NONE;
    if ((ADC_USR_MIN <= data) && (data <= ADC_USR_MAX))  ret = SSU_USER;
    if ((ADC_S1_MIN <= data) && (data <= ADC_S1_MAX))  ret = SSU_S1;
    if ((ADC_S2_MIN <= data) && (data <= ADC_S2_MAX))  ret = SSU_S2;
    if (ret != SSU_NONE) {
        return ret;
    }  
    else return 0; //==按键按下是1-2-3 返回0说明无任何按键按下
}

//循环函数
static void *GpioADCTask(const char *arg)
{
    (void) arg;
    while(1)
    {
        button_adc_get();  //获取adc值
        int key_status =button_pressed_check(button_adc_get()); //判断是哪个按下
        printf("key_status: %d \n",key_status); 
        switch (key_status){
             case SSU_NONE:  //无按键按下-led灭
                    IoTGpioSetOutputVal(LED_GPIO_9,1);   break; 
             case SSU_USER:  //==USER键-led闪烁2下后灭
                    IoTGpioSetOutputVal(LED_GPIO_9,0); 
                    usleep(300000);  
                    IoTGpioSetOutputVal(LED_GPIO_9,1); 
                    usleep(300000);  
                    IoTGpioSetOutputVal(LED_GPIO_9,0); 
                    usleep(300000);  
                    IoTGpioSetOutputVal(LED_GPIO_9,1);  break; 
             case SSU_S1: //S1-led闪一下灭
                    IoTGpioSetOutputVal(LED_GPIO_9,0); 
                    usleep(30000);  
                    IoTGpioSetOutputVal(LED_GPIO_9,1);    break;       
             case SSU_S2: //S2按下-led一直亮  
                    IoTGpioSetOutputVal(LED_GPIO_9,0);   break;
             defualt : //无  led不亮
                    IoTGpioSetOutputVal(LED_GPIO_9,1);   break; 
        }
        usleep(100); //==轮询时间控制 */
    }
    return NULL;
}

//==任务入口函数
void GpioADCEntry(void)
{
    IoTGpioInit(KEY_TEST_GPIO);                          //==初始化GPIO5
    hi_io_set_func(KEY_TEST_GPIO,HI_IO_FUNC_GPIO_5_GPIO);//==GPIO5作为普通io接口
    IoTGpioSetDir(KEY_TEST_GPIO,IOT_GPIO_DIR_IN);        //==io方向-输入
    hi_io_set_pull(KEY_TEST_GPIO, HI_IO_PULL_UP);        //==上拉输入
   // IoSetPull(KEY_TEST_GPIO, HI_IO_PULL_UP); //自行封装在iot_gpio.h 2021.09.23

    IoTGpioInit(LED_GPIO_9);
    IoTGpioSetDir(LED_GPIO_9,IOT_GPIO_DIR_OUT);         //==载板led初始化

    osThreadAttr_t attr; //==创建任务
    attr.name = "GpioADCTask";                 //==指定线程运行的任务
    attr.attr_bits = 0U;                    //==
    attr.cb_mem = NULL;                     //==
    attr.cb_size = 0U;                      //==
    attr.stack_mem = NULL;                  //==
    attr.stack_size = KEY_TASK_STACK_SIZE;  //==
    attr.priority = KEY_TASK_PRIO;          //==优先权限 

    if (osThreadNew((osThreadFunc_t)GpioADCTask, NULL, &attr) == NULL) {
        printf("[GpioADCEntry] Falied to create GpioADCTask!\n");
    }
}
SYS_RUN(GpioADCEntry); //==ohos_init.h中定义的宏 让一个函数在系统启动时自动执行

